home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / program / recio214.zip / RECIO.C < prev    next >
C/C++ Source or Header  |  1996-06-14  |  15KB  |  412 lines

  1. /*****************************************************************************
  2.    MODULE: recio.c
  3.   PURPOSE: record input/output functions
  4. COPYRIGHT: (C) 1994-1996, William Pierpoint
  5.  COMPILER: Borland C Version 3.1
  6.        OS: MSDOS Version 6.2
  7.   VERSION: 2.14
  8.   RELEASE: June 14, 1996
  9. *****************************************************************************/
  10.  
  11. #include <ctype.h>
  12. #include <errno.h>
  13. #include <float.h>
  14. #include <limits.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18.  
  19. #include "recio.h"
  20.  
  21. #define rcol(rp)         ((rp)->r_colno)
  22. #define rflags(rp)       ((rp)->r_flags)
  23. #define rfd(rp)          ((rp)->r_fd)
  24. #define rfp(rp)          ((rp)->r_fp)
  25. #define rreclen(rp)      ((rp)->r_reclen)
  26. #define rrecsiz(rp)      ((rp)->r_recsiz)
  27. #define rfldsiz(rp)      ((rp)->r_fldsiz)
  28. #define rfldch(rp)       ((rp)->r_fldch)
  29. #define rtxtch(rp)       ((rp)->r_txtch)
  30. #define rtmfmt(rp)       ((rp)->r_tmfmt)
  31.  
  32. /* private module variables */
  33. static REC *_RECS = NULL;              /* ptr to array of RECs */
  34. static char _tmfmt[] = "%m/%d/%y";     /* default time format string */
  35.  
  36. static REC rin  = { 1,      0,    stdin,  "stdin",     0L,
  37.                     0,      0,        0,        0,   NULL, 
  38.                     0,   NULL, RECFLDCH, RECTXTCH,  _tmfmt, RECIN };
  39.  
  40. static REC rout = { 2, _R_WRT,   stdout, "stdout",     0L, 
  41.                     0,      0,        0,        0,   NULL, 
  42.                     0,   NULL, RECFLDCH, RECTXTCH, _tmfmt, RECOUT };
  43.  
  44. static REC rerr = { 3, _R_WRT,   stderr, "stderr",     0L, 
  45.                     0,      0,        0,        0,   NULL, 
  46.                     0,   NULL, RECFLDCH, RECTXTCH, _tmfmt, RECERR };
  47.  
  48. #if defined (__MSDOS__) || (MSDOS)
  49. static REC rprn = { 4, _R_WRT,   stdprn, "stdprn",     0L, 
  50.                     0,      0,        0,        0,   NULL, 
  51.                     0,   NULL, RECFLDCH, RECTXTCH, _tmfmt, RECPRN };
  52. #define NREC      4          /* number of static record streams */
  53. #else
  54. #define NREC      3
  55. #endif
  56.  
  57. #define ROPEN_MIN NREC       /* reserved for recin, etc */
  58. #define ROPEN     max(ROPEN_MAX, ROPEN_MIN)
  59.  
  60. /* public variables */
  61. REC *recin = &rin;
  62. REC *recout = &rout;
  63. REC *recerr = &rerr;
  64. #if defined (__MSDOS__) || (MSDOS)
  65. REC *recprn = &rprn;
  66. #endif
  67.  
  68. /* friend variables */
  69. char _r_nsbuf[NSBUFSIZ];     /* buffer for numeric to string conversions */
  70. void (*_r_errfn)(REC *);     /* pointer to error message function */
  71.  
  72. /* Support functions */
  73. /****************************************************************************/
  74. static void                  /* returns nothing                             */
  75.     _rexit(                  /* at program exit, clean up                   */
  76.         void)                /* no arguments                                */
  77. /****************************************************************************/
  78. {
  79.     /* free recin buffers */
  80.     free(rflds(recin));
  81.     free(rrecs(recin));
  82.     rflds(recin) = NULL;
  83.     rfldsiz(recin) = 0;
  84.     rrecs(recin) = NULL;
  85.     rrecsiz(recin) = 0;
  86.     rreclen(recin) = 0;
  87.  
  88.     /* ensure all record streams closed */
  89.     rcloseall();
  90. }
  91.  
  92. /****************************************************************************/
  93. void                         /* return error number (0=no error)            */
  94.     _rsetexitfn(             /* register _rexit function with atexit()      */
  95.         REC *rp)             /* record pointer                              */
  96. /****************************************************************************/
  97. {
  98.     static int once=0;       /* register exit fn only once */
  99.  
  100.     if (!once) {
  101.  
  102.         /* execute this path at most one time */
  103.         once++;
  104.  
  105.         /* if atexit() fails to register _rexit() function */
  106.         if (atexit(_rexit)) {
  107.  
  108.            /* register warning */
  109.            rsetwarn(rp, R_WNOREG);
  110.         }
  111.     }
  112.  
  113. /****************************************************************************/
  114. int                          /* return error number (0=no error)            */
  115.     _rmoderror(              /* check for mode error                        */
  116.         REC *rp,             /* record pointer                              */
  117.         int mode)            /* mode (0=read; !0=write/append)              */
  118. /****************************************************************************/
  119. {
  120.     int errnum=0;            /* error number (0=mode ok, !0=invalid mode) */
  121.     unsigned smode;          /* stream mode */
  122.  
  123.     /* if stream _R_WRT flag does not match mode */
  124.     smode = rflags(rp) & _R_WRT;
  125.     if ((mode && !smode) || (!mode && smode)) {
  126.         errnum = rseterr(rp, R_EINVMOD);
  127.     }
  128.     return errnum;
  129. }
  130.  
  131. /****************************************************************************/
  132. int                          /* return !0 if ready; 0 if in error state     */
  133.     _risready(               /* see if record stream is ready               */
  134.         REC *rp,             /* record pointer                              */
  135.         int mode)            /* mode (0=read; !0=write/append)              */
  136. /****************************************************************************/
  137. {
  138.     int errnum=0;            /* error number */
  139.  
  140.     /* test for valid record pointer */
  141.     if (!risvalid(rp)) {
  142.         errnum = rseterr(NULL, EINVAL);
  143.         goto done;
  144.     }
  145.     
  146.     /* check mode */
  147.     errnum = _rmoderror(rp, mode);
  148.     if (errnum) goto done;
  149.  
  150.     /* if record 0 and write mode, set record number to 1 */
  151.     if (!rrecno(rp) && mode) rrecno(rp)++;
  152.  
  153.     /* test for any previous error */
  154.     errnum = rerror(rp);
  155.  
  156. done:
  157.     return (!(errnum));
  158. }
  159.  
  160. /****************************************************************************/
  161. static void                  /* returns nothing                             */
  162.     _rfree(                  /* free the memory allocated to a record       */
  163.         REC *rp)             /* record pointer                              */
  164. /****************************************************************************/
  165. {
  166.     if (risvalid(rp)) {
  167.         free(rflds(rp));
  168.         free(rrecs(rp));
  169.         if (rfp(rp)) fclose(rfp(rp));
  170.         memset(rp, 0, sizeof(REC));
  171.     }
  172. }
  173.  
  174. /* User functions */
  175. /****************************************************************************/
  176. REC *                        /* return record pointer                       */
  177.     ropen(                   /* open a record stream for reading            */
  178.         const char *fname,   /* name of file to open                        */
  179.         const char *mode)    /* type of mode used to open file              */
  180. /****************************************************************************/
  181. {
  182.     REC *rp = _RECS;         /* record pointer */
  183.     int  i;                  /* count of REC structures */
  184.     int  ch;                 /* first character of mode */
  185.     
  186.     errno = 0;
  187.  
  188.     /* only modes currently supported are "r", "w", and "a" */
  189.     ch = tolower(*mode);
  190.     if (!(ch=='r' || ch=='w' || ch=='a')) {
  191.         rp = NULL;
  192.         rseterr(NULL, EINVAL);
  193.         goto done;
  194.     }
  195.  
  196.     /* allocate memory for array of REC structures */
  197.     if (!rp) {
  198.         do {
  199.             /* note: no memory allocation needed for recin, etc */
  200.             rp = _RECS = (REC *) calloc(ROPEN-NREC, sizeof(REC));
  201.             if (!rp) {
  202.                 if (rseterr(NULL, ENOMEM)) goto done;
  203.             }
  204.         } while (!rp);
  205.     }
  206.  
  207.     /* search thru REC structures until empty position found */
  208.     for (i=NREC+1; i <= ROPEN; i++, rp++) {
  209.         if (!rfd(rp)) {
  210.             rfd(rp) = i;
  211.             break;
  212.         }
  213.     }
  214.     /* error if out of positions */
  215.     if (i > ROPEN) {
  216.         rp = NULL;
  217.         rseterr(NULL, EMFILE);
  218.         goto done;
  219.     }
  220.  
  221.     /* open file */
  222.     rfp(rp) = fopen(fname, mode);
  223.     if (!rfp(rp)) {
  224.         rclose(rp);
  225.         rp = NULL;
  226.         /* if error other than path/file not found */
  227.         if (errno != ENOENT) {
  228.             rseterr(NULL, errno);
  229.         }
  230.         goto done;
  231.     }
  232.  
  233.     /*